# sql.py
# 2010 - Matthew Fay and Jodyann Coley
# 
# 2006 - Eric Lieberman and Mike Lin

# The class SemanticSQL implemented in this file handles all queries to the MySQL database.
# Its chief functionality is to translate the semantic data structures constructed by
# lab_rules.py into the necessary SQL queries to insert facts into the database are query
# for existing facts.

# some utility functions
def sql_quote(s):
	if (str(s) == '-'):
		return "NULL"
	else:
		return "'" + str(s) + "'"

def sql_where_clauses(lst):
	fst = True
	rtn = ""
	for i in range(len(lst)):
		name = lst[i][0]
		value = lst[i][1]
		if str(value) != 'NULL':
			if not(fst):
				rtn += " AND "
			else:
				fst = False
			rtn += name + "=" + str(value)
	return(rtn)

from logger import Logger

# for simplicity, lab_rules handles multiple adjectives by having each adjective except
# the last modify the next adjective (i.e. yellow rabid dog parses as dog[mod rabid[mod yellow]]
# unroll_mods "unrolls" this into a flat list, e.g. [yellow, rabid]
def unroll_mods(rootmod):
	if str(rootmod) == '-':
		return([])
	else:
		x = unroll_mods(rootmod.getFeature("mod").value())
		x.append(rootmod.symbol())
		return x

# Do something about 'None's
#def translate_list(lst,top=True):
#	if len(lst) == 0:
#		return ""
#	elif len(lst) == 1:
#		return str(lst[0])
#	elif len(lst) == 2:
#		if top:
#			return ("%s and %s" % (str(lst[0]),str(lst[1])))
#		else:
#			return ("%s, and %s" % (str(lst[0]),str(lst[1])))
#	else:
#		hd = lst.pop(0)
#		return ("%s, %s" % (str(hd),translate_list(lst,False)))

def translate_list(lst):
	i = 0
	while i < len(lst):
		if str(lst[i]) == "None":
			del lst[i]
			i = i - 1
		i = i + 1
	if len(lst) == 0:
		return "None"
	elif len(lst) == 1:
		return str(lst[0])
	elif len(lst) == 2:
		return str(lst[0]) + " and " + str(lst[1])
	else:
		i = 0
		list = ""
		while i < len(lst):
			if i == len(lst)-1:
				list = list + ", and " + str(lst[i])
			elif i == 0:
				list = list + str(lst[i])
			else:
				list = list + ", " + str(lst[i])
			i = i+1
		return list
		
class SemanticSQL(object):
	# INTERNAL METHODS
	
	def __init__(self,dbc):
		self._dbc = dbc
		self._cursor = None
		self._log = []

	def getCursor(self):
		if self._cursor != None:
			return self._cursor
		else:
			self._cursor = self._dbc.cursor()
			return self._cursor
	def getLog(self,final=False):
		retval = self._log
		if retval == []:
			self._log = [Logger()]
			retval = (self._log)[0]
		else:
			retval = retval[0]
		if final:
			self._log = []
		return retval

	# insert several modifiers for the target
	def insert_mods(self,target_id,mods):
		def mod_tuple(target_id,mod):
			return ("('%s',%s)" % (mod,target_id))
		for mod in mods:
			sql = "SELECT `mod` FROM `Mod` WHERE `mod` = %s AND `target` = %s" % (sql_quote(mod), sql_quote(target_id))
			#print sql
			self.getCursor().execute(sql)
			rslt = self.getCursor().fetchall()
			if len(rslt) == 0:
				sql = "INSERT INTO `Mod` (`mod`,`target`) VALUES %s" % (mod_tuple(target_id,mod))
				print sql
				self.getCursor().execute(sql)
				self.getLog().addMessage("inserting modifiers for the object",sql,"OK")
				sql = "INSERT INTO `Event` (`action`,`agent`,`tense`,`adjective`) VALUES ('be','%s','present','%s')" % (target_id,mod)
				self.getCursor().execute(sql)
				sql = "INSERT INTO `Event` (`action`,`agent`,`tense`,`adjective`) VALUES ('be','%s','past','%s')" % (target_id,mod)
				self.getCursor().execute(sql)
		#sql = "INSERT INTO `Mod` (`mod`,`target`) VALUES %s" % (",".join([mod_tuple(target_id,x) for x in mods]))
		# print sql
	
	# gets the plural form from db, replace with kimmo
	def get_plural(self,noun):
		sql = "SELECT nounp FROM noun WHERE noun='"+noun+"'"
		#print sql
		self.getCursor().execute(sql)
		result = self.getCursor().fetchall()
		for record in result:
			return record[0]
	
	# insert a new object and return its database id
	def insert_object(self,obj):
		name = obj.getFeature("name").value()
		# print name
		if str(name) != '-':
			sql = "INSERT INTO Object(`name`,`type`,`definite`) VALUES (%s,NULL,NULL)" % sql_quote(name)
			# print sql
			self.getCursor().execute(sql)
			sql2 = "SELECT LAST_INSERT_ID()"
			self.getCursor().execute(sql2)
			id = str(self.getCursor().fetchall()[0][0])
			self.getLog().addMessage("inserting a new named object",sql,("OK, id = %s" % id))
			
			mods = unroll_mods(obj.getFeature("mod").value())
			if len(mods) > 0:
				self.insert_mods(id,mods)
			return(id)
		else:
			type = obj.getFeature("type").value()
			definite = obj.getFeature("definite").value()
			if str(definite) != "-" and str(definite) != "+":
				#Search for signular
				singsql = "SELECT noun FROM noun WHERE nounp = '%s'" % (str(type))
				self.getCursor().execute(singsql)
				rslt = self.getCursor().fetchall()
				if len(rslt) > 0:
					type = rslt[0][0]
					print type
			sql = "INSERT INTO Object(`name`,`type`,`definite`) VALUES (NULL,'%s','%s')" % (type,definite)
			self.getCursor().execute(sql)
			sql2 = "SELECT LAST_INSERT_ID()"
			self.getCursor().execute(sql2)
			id = str(self.getCursor().fetchall()[0][0])

			self.getLog().addMessage("inserting a new unnamed object",sql,("OK, id = %s" % id))
			mods = unroll_mods(obj.getFeature("mod").value())
			if len(mods) > 0:
				self.insert_mods(id,mods)
				
			return(id)
	
	# return the database ID of this object, optionally inserting it if it doesn't exist
	def resolve_object(self,obj,add,generalizeDefinite=False,pluralize=False):
		name = obj.getFeature("name").value()
		if (str(name) != '-'):
			wheres = sql_where_clauses([["name",sql_quote(name)]])
			sql = "SELECT id FROM Object WHERE %s" % wheres
			self.getCursor().execute(sql)
			rslt = self.getCursor().fetchall()
			
			if len(rslt) > 0:
				id = str(rslt[0][0])
				self.getLog().addMessage("resolving named object",sql,("OK, id = %s" % id))
				mods = unroll_mods(obj.getFeature("mod").value())
				if len(mods) > 0:
					self.insert_mods(id,mods)
				return(id)
			elif add:
				self.getLog().addMessage("resolving named object",sql,"not found, will insert")
				return(self.insert_object(obj))
			else:
				self.getLog().addMessage("resolving named object",sql,"not found, failing")
				raise Exception("unknown name " + name)
		else:
			type = obj.getFeature("type").value()
			definite = obj.getFeature("definite").value()
			if (pluralize==True and str(definite)=="-"):
				#print "Begin Pluralize:"
				type = self.get_plural(str(type))
				#print "Pluralize Complete"
			# If definite is a word convert from plural to singular
			if str(definite) != "-" and str(definite) != "+":
				#Search for signular
				singsql = "SELECT noun FROM noun WHERE nounp = '%s'" % (str(type))
				self.getCursor().execute(singsql)
				rslt = self.getCursor().fetchall()
				if len(rslt) > 0:
					type = rslt[0][0]
					print type
			if str(type) != '-':
				mods = unroll_mods(obj.getFeature("mod").value())

				# generalization of definite: so that the question "does john like a dog" will find the fact "john likes the dog"
				defClause = " AND Object.definite = '%s'" % definite
				if generalizeDefinite and str(definite) == "-":
					defClause = ""
					
				if len(mods) > 0:
					modWheres = " OR ".join([("Mod.mod = '%s'" % mod) for mod in mods])
					sql = "SELECT CASE WHEN COUNT(*) = %d THEN Object.id ELSE NULL END FROM Object, `Mod` WHERE Object.type='%s'%s AND Mod.target = Object.id AND (%s)" % (len(mods),type,defClause,modWheres)
				else:
					sql = "SELECT id FROM Object WHERE `type`='%s'%s" % (type,defClause)
				self.getCursor().execute(sql)
				rslt = self.getCursor().fetchall()
				if len(rslt) > 0 and rslt[0][0] != None:
					id = str(rslt[0][0])
					self.getLog().addMessage("resolving unnamed object",sql,("OK, id = %s" % id))
					return(id)
				elif add:
					self.getLog().addMessage("resolving unnamed object",sql,("not found, will insert"))
					return(self.insert_object(obj))
				else:
					self.getLog().addMessage("resolving unnamed object",sql,("not found, failing"))
					raise Exception("unknown entity " + type)
			else:
				return "NULL"

	# translate an object into nice english, including pulling in any modifiers
	def translate_object(self,id,name,type,definite):
		if name != None:
			return name
		else:
			sql = "SELECT `mod` FROM `Mod` WHERE target = %s" % id
			self.getCursor().execute(sql)
			mods = [x[0] for x in self.getCursor().fetchall()]
			self.getLog().addMessage("getting modifiers for translation",sql,str(mods))
			det = "a"
			if definite == '+':
				det = "the"
			if len(mods) > 0:
				return ("%s %s %s" % (det,(" ".join(mods)),type))
			else:
				return ("%s %s" % (det,type))
			
	# translate a location into nice english with the preposition and target
	def translate_loc(self,loc_prep,loc_target_id):
		if loc_target_id != None:
			sql = "SELECT `name`,`type`,`definite` FROM `Object` WHERE id = %s" % loc_target_id
			self.getCursor().execute(sql)
			rst=self.getCursor().fetchall()
			if len(rst) > 0:
				obj = self.translate_object(loc_target_id,rst[0][0],rst[0][1],rst[0][2])
				return ("%s %s" % (loc_prep,obj))
			
	def translate_adv(self,adverb):
		return adverb

	# utility: for wh- questions, separate the variable ?what from the fully specified features
	def features_and_variables(self,lst):
		feats = []
		vars = []
		for i in range(len(lst)):
			name = lst[i][0]
			value = lst[i][1]
			# print (name, value)
			if str(value)[0] == '?':
				vars.append([name,value.varname()])
			else:
				feats.append([name,self.resolve_object(value,False)])
		return (feats, vars)

	# EXTERNAL METHODS
	def add(self,fact):
		print "FACT ADD"
		print fact
		#print "FACT"
		table = fact.symbol()
		action = sql_quote(fact.getFeature("action").value())
		tense = sql_quote(fact.getFeature("tense").value())

		agent_id = self.resolve_object(fact.getFeature("agent").value(),True)
		patient_id = self.resolve_object(fact.getFeature("patient").value(),True)
		beneficiary_id = self.resolve_object(fact.getFeature("beneficiary").value(),True)

		loc_prep = sql_quote(fact.getFeature("location").value().getFeature("loc_prep").value())
		loc_target_id = self.resolve_object(fact.getFeature("location").value().getFeature("loc_target").value(),True)
		instrument_id = self.resolve_object(fact.getFeature("instrument").value(),True)

		adverb = sql_quote(fact.getFeature("adverb").value())
		adjective = sql_quote(fact.getFeature("adjective").value())
		negation = str(fact.getFeature("negation").value())
		if negation == "-":
			negation = "False"

		sql = "INSERT INTO %s VALUES (%s)" % (table,",".join([action,agent_id,patient_id,beneficiary_id,tense,loc_prep,loc_target_id,instrument_id,adverb,adjective,negation]))
		print sql
		self.getCursor().execute(sql)
		self.getLog().addMessage("adding fact",sql,"OK")
		self.getLog().setFinalAnswer("OK")
		return self.getLog(final=True)

	def getModsById(self,objid):
		sql = "SELECT `mod` FROM `Mod` WHERE `target` = %s" % (objid)
		self.getCursor().execute(sql)
		fetched = self.getCursor().fetchall()
		j = 0
		cmod = []
		while j < len(fetched):
			cmod.append(fetched[j][0])
			j = j+1
		return cmod
		
	def getObjectClasses(self,objid,tense,allonly=True):
		sql = "SELECT patient FROM Event WHERE agent = %s AND negation = 0 AND tense = '%s' AND action = 'be'" % (objid,tense)
		self.getCursor().execute(sql)
		fetched = self.getCursor().fetchall()
		
		i = 0
		classids = []
		while i < len(fetched):
			classids.append(fetched[i][0])
			i=i+1
		# Now we have ids of classes
		# Now get mods of classes
		# and the types
		i = 0
		mods = []
		types = []
		while i < len(classids):
			sql = "SELECT `type` FROM `Object` WHERE `id` = %s" % (classids[i])
			self.getCursor().execute(sql)
			fetched = self.getCursor().fetchall()
			types.append(fetched[0][0])
			mods.append(self.getModsById(classids[i]))
			i=i+1
		# NOW search for categories!
		i = 0
		categoryids = []
		while i < len(classids):
			sql = "SELECT `id` FROM `Object` WHERE `type` = '%s' AND `definite` = 'all'" % (types[i])
			self.getCursor().execute(sql)
			fetched = self.getCursor().fetchall()
			print fetched
			j = 0
			while j < len(fetched):
				cmods = self.getModsById(fetched[j][0])
				if len(cmods)==0:
					if not fetched[j][0] in categoryids:
						categoryids.append(fetched[j][0])
				else:
					k = 0
					while k < len(cmods):
						if cmods[k] in mods[i]:
							if not fetched[j][0] in categoryids:
								categoryids.append(fetched[j][0])
						k = k + 1
				j = j + 1
			i = i + 1
		
		print categoryids
		return categoryids
	
	def match(self,fact):
		print "MATCH"
		print fact
		table = fact.symbol()
		action = fact.getFeature("action").value()
		tense = fact.getFeature("tense").value()
		adverb = sql_quote(fact.getFeature("adverb").value())
		adjective = sql_quote(fact.getFeature("adjective").value())
		loc_prep = fact.getFeature("location").value().getFeature("loc_prep").value()
		try:
			agent_id = self.resolve_object(fact.getFeature("agent").value(),False,generalizeDefinite=True)
		except Exception:
			try:
				if str(fact.getFeature("agent").value().getFeature("definite").value()) == "-":
					agent_id = self.resolve_object(fact.getFeature("agent").value(),False,generalizeDefinite=True,pluralize=True)
				else:
					raise Exception()
			except Exception:
				self.getLog().addMessage("yes/no question","-","No, unknown object")
				self.getLog().setFinalAnswer("No")
				return self.getLog(final=True)
		try:
			patient_id = self.resolve_object(fact.getFeature("patient").value(),False,generalizeDefinite=True)
		except Exception:
			try:
				if str(fact.getFeature("patient").value().getFeature("definite").value())=="-":
					patient_id = self.resolve_object(fact.getFeature("patient").value(),False,generalizeDefinite=True,pluralize=True)
				else:
					raise Exception()
			except Exception:
				self.getLog().addMessage("yes/no question","-","No, unknown object")
				self.getLog().setFinalAnswer("No")
				return self.getLog(final=True)
		try:
			beneficiary_id = self.resolve_object(fact.getFeature("beneficiary").value(),False,generalizeDefinite=True)
		except Exception:
			try:
				if str(fact.getFeature("beneficiary").value().getFeature("definite").value())=="-":
					beneficiary_id = self.resolve_object(fact.getFeature("beneficiary").value(),False,generalizeDefinite=True,pluralize=True)
				else:
					raise Exception()
			except Exception:
				self.getLog().addMessage("yes/no question","-","No, unknown object")
				self.getLog().setFinalAnswer("No")
				return self.getLog(final=True)
		try:
			loc_target_id = self.resolve_object(fact.getFeature("location").value().getFeature("loc_target").value(),False,generalizeDefinite=True)
		except Exception:
			try:
				if str(fact.getFeature("location").value().getFeature("loc_target").value().getFeature("definite").value())=="-":
					loc_target_id = self.resolve_object(fact.getFeature("location").value().getFeature("loc_target").value(),False,generalizeDefinite=True,pluralize=True)
				else:
					raise Exception()
			except Exception:
				self.getLog().addMessage("yes/no question","-","No, unknown object")
				self.getLog().setFinalAnswer("No")
				return self.getLog(final=True)
		try:
			instrument_id = self.resolve_object(fact.getFeature("instrument").value(),False,generalizeDefinite=True)
		except Exception:
			try:
				if str(fact.getFeature("instrument").value().getFeature("definite").value())=="-":
					instrument_id = self.resolve_object(fact.getFeature("instrument").value(),False,generalizeDefinite=True,pluralize=True)
				else:
					raise Exception()
			except Exception:
				self.getLog().addMessage("yes/no question","-","No, unknown object")
				self.getLog().setFinalAnswer("No")
				return self.getLog(final=True)
		
		negation = str(fact.getFeature("negation").value())
		wheres = sql_where_clauses([["action",sql_quote(action)],["agent",agent_id],["patient",patient_id],["beneficiary",beneficiary_id],["tense",sql_quote(tense)],["adverb",adverb],["loc_prep",sql_quote(loc_prep)],["loc_target",loc_target_id],["instrument",instrument_id],["negation",negation]])
		sql = "SELECT CASE WHEN COUNT(*) > 0 THEN 'Yes' ELSE 'No' END FROM %s WHERE %s" % (table,wheres)
		print sql
		self.getCursor().execute(sql)
		fetched = self.getCursor().fetchall()
		rslt = fetched[0][0]
		self.getLog().addMessage("yes/no question",sql,rslt)
		tryagain = False
		if str(rslt)=="No":
			if str(fact.getFeature("agent").value().getFeature("definite").value()) == "-":
				try:
					agent_idp=agent_id
					agent_id = self.resolve_object(fact.getFeature("agent").value(),False,generalizeDefinite=True,pluralize=True)
					tryagain = True
				except Exception:
					agent_id=agent_idp
			if str(fact.getFeature("patient").value().getFeature("definite").value()) == "-":
				try:
					patient_idp=patient_id
					patient_id = self.resolve_object(fact.getFeature("patient").value(),False,generalizeDefinite=True,pluralize=True)
					tryagain = True
				except Exception:
					patient_id=patient_idp
			if str(fact.getFeature("beneficiary").value().getFeature("definite").value()) == "-":
				try:
					beneficiary_idp=beneficiary_id
					beneficiary_id = self.resolve_object(fact.getFeature("beneficiary").value(),False,generalizeDefinite=True,pluralize=True)
					tryagain = True
				except Exception:
					beneficiary_id=beneficiary_idp
		if tryagain==True:
			wheres = sql_where_clauses([["action",sql_quote(action)],["agent",agent_id],["patient",patient_id],["beneficiary",beneficiary_id],["tense",sql_quote(tense)],["adverb",adverb],["loc_prep",sql_quote(loc_prep)],["loc_target",loc_target_id],["instrument",instrument_id],["negation",negation]])
			sql = "SELECT CASE WHEN COUNT(*) > 0 THEN 'Yes' ELSE 'No' END FROM %s WHERE %s" % (table,wheres)
			#sql = "SELECT `negation` FROM %s WHERE %s" % (table,wheres)
			#print sql
			self.getCursor().execute(sql)
			fetched = self.getCursor().fetchall()
			rslt = fetched[0][0]
			self.getLog().addMessage("yes/no question",sql,rslt)
		#Check classes!#
		if str(rslt)=="No":
			classids = self.getObjectClasses(agent_id,tense)
			print self.idsToWhere("agent",classids)
			
			sql = "SELECT CASE WHEN COUNT(*) > 0 THEN 'Yes' ELSE 'No' END FROM %s WHERE %s" % (table,classids)
		self.getLog().setFinalAnswer(rslt)
		return self.getLog(final=True)

	def idsToWhere(self, position ,ids):
		if len(ids) == 0:
			return "1 = 1"
		if len(ids) > 0:
			str = "(%s = %s" % (position,ids[0])
			i = 1
			while i < len(ids):
				str = str + " OR %s = %s" % (position,ids[i])
				i = i + 1
			str = str + ")"
			return str

	def matchVar(self, fact):
		table = fact.symbol()
		#print "FACT VAR"
		print fact
		#print "FACT"
		try:
			(feats,vars) = self.features_and_variables([[x,fact.getFeature(x).value()] for x in ["agent","patient","beneficiary"]])
		except Exception:
			self.getLog().addMessage("wh- question","-","I don't know, unknown object")
			self.getLog().setFinalAnswer("I don't know.")
			return self.getLog(final=True)
		negation = str(fact.getFeature("negation").value())
		feats = [["action",sql_quote(fact.getFeature("action").value())],["tense",sql_quote(fact.getFeature("tense").value())],
				 ["adverb",sql_quote(fact.getFeature("adverb").value())],
				 ["loc_prep",sql_quote(fact.getFeature("location").value().getFeature("loc_prep").value())],
				 ["loc_target",self.resolve_object(fact.getFeature("location").value().getFeature("loc_target").value(), True)],
				 ["instrument",self.resolve_object(fact.getFeature("instrument").value(), True)]] + feats

#		vars = ".".join([x[0] for x in vars])
		wheres = sql_where_clauses(feats)
		# print vars
		sql = "SELECT `id`,`name`,`type`,`definite` FROM %s, Object WHERE negation = %s AND %s AND Object.id = %s" % (table,negation,wheres,vars[0][0])
		print sql
		self.getCursor().execute(sql)
		allrslt=self.getCursor().fetchall()
		self.getLog().addMessage("wh- question",sql,str(allrslt))
		if len(allrslt) > 0:
			translations = [self.translate_object(allrslt[i][0],allrslt[i][1],allrslt[i][2],allrslt[i][3]) for i in range(len(allrslt))]
			rslt = translate_list(translations)
			self.getLog().setFinalAnswer(rslt)
		else:
			rslt = "I don't know."
			self.getLog().setFinalAnswer(rslt)
		return self.getLog(final=True)

	def matchAdv(self, fact):
		table = fact.symbol()
		#print "FACT MATCH ADV"
		print fact
		#print "FACT"
		action = fact.getFeature("action").value()
		tense = fact.getFeature("tense").value()
		#adverb = sql_quote(fact.getFeature("adverb").value())
		try:
			agent_id = self.resolve_object(fact.getFeature("agent").value(),False,generalizeDefinite=True)
			patient_id = self.resolve_object(fact.getFeature("patient").value(),False,generalizeDefinite=True)
			beneficiary_id = self.resolve_object(fact.getFeature("beneficiary").value(),False,generalizeDefinite=True)
			loc_prep = sql_quote(fact.getFeature("location").value().getFeature("loc_prep").value())
			loc_target_id = self.resolve_object(fact.getFeature("location").value().getFeature("loc_target").value(),True)
			instrument_id = self.resolve_object(fact.getFeature("instrument").value(),True)
		except Exception:
			self.getLog().addMessage("yes/no question","-","No, unknown object")
			self.getLog().setFinalAnswer("No")
			return self.getLog(final=True)
			
		negation = str(fact.getFeature("negation").value())
		wheres = sql_where_clauses([["action",sql_quote(action)],["agent",agent_id],["patient",patient_id],["beneficiary",beneficiary_id],["tense",sql_quote(tense)],["negation",negation]])
		sql = "SELECT `adverb` FROM %s WHERE %s" % (table,wheres)
		# print sql
		self.getCursor().execute(sql)
		allrslt=self.getCursor().fetchall()
		self.getLog().addMessage("how question",sql,allrslt)
		rslt = ""
		if len(allrslt) > 0:
			translations = [self.translate_adv(allrslt[i][0]) for i in range(len(allrslt))]
			rslt = translate_list(translations)
		else:
			rslt = "I don't know"
		if str(rslt)=="None":
			rslt = "I don't know"
		self.getLog().setFinalAnswer(rslt)
		return self.getLog(final=True)
	
	def matchLoc(self, fact):
		table = fact.symbol()
		#print "FACT LOCATION"
		print fact
		#print "FACT"
		try:
			action = fact.getFeature("action").value()
			tense = fact.getFeature("tense").value()
			agent_id = self.resolve_object(fact.getFeature("agent").value(),False,generalizeDefinite=True)
			patient_id = self.resolve_object(fact.getFeature("patient").value(),False,generalizeDefinite=True)
			beneficiary_id = self.resolve_object(fact.getFeature("beneficiary").value(),False,generalizeDefinite=True)
			adverb = sql_quote(fact.getFeature("adverb").value())
			instrument_id = self.resolve_object(fact.getFeature("instrument").value(),False,generalizeDefinite=True)
		except Exception:
			self.getLog().addMessage("location question","-","I don't know, unknown object")
			self.getLog().setFinalAnswer("I don't know.")
			return self.getLog(final=True)
		
		negation = str(fact.getFeature("negation").value())
		wheres = sql_where_clauses([["action",sql_quote(action)],["tense",sql_quote(tense)],["agent",agent_id],["patient",patient_id],["beneficiary",beneficiary_id],["adverb",adverb],["instrument",instrument_id],["negation",negation]])
		sql = "SELECT `loc_prep`, `loc_target`FROM %s WHERE %s" % (table,wheres)
		self.getCursor().execute(sql)
		allrslt=self.getCursor().fetchall()
		self.getLog().addMessage("location question",sql,allrslt)
		rslt = ""
		if len(allrslt) > 0:
			translations = [self.translate_loc(allrslt[i][0], allrslt[i][1]) for i in range(len(allrslt))]
			rslt = translate_list(translations)
		if str(rslt)=="None":
			rslt = "I don't know"
		self.getLog().setFinalAnswer(rslt)
		return self.getLog(final=True)
	
	
	def matchIns(self, fact):
		table = fact.symbol()
		#print "FACT INSTRUMENT"
		print fact
		#print "FACT"
		try:
			(feats,vars) = self.features_and_variables([[x,fact.getFeature(x).value()] for x in ["agent","patient","beneficiary","instrument"]])
		except Exception:
			self.getLog().addMessage("instrument question","-","I don't know, unknown object")
			self.getLog().setFinalAnswer("I don't know.")
			return self.getLog(final=True)
		
		feats = [["action",sql_quote(fact.getFeature("action").value())],["tense",sql_quote(fact.getFeature("tense").value())],
				 ["adverb",sql_quote(fact.getFeature("adverb").value())],
				 ["loc_prep",sql_quote(fact.getFeature("location").value().getFeature("loc_prep").value())],
				 ["loc_target",self.resolve_object(fact.getFeature("location").value().getFeature("loc_target").value(), True)]] + feats

		wheres = sql_where_clauses(feats)
		negation = str(fact.getFeature("negation").value())
		sql = "SELECT `id`,`name`,`type`,`definite` FROM %s, Object WHERE Event.negation = %s AND %s AND Object.id = %s" % (table,negation,wheres,vars[0][0])
		self.getCursor().execute(sql)
		allrslt=self.getCursor().fetchall()
		self.getLog().addMessage("instrument question",sql,str(allrslt))
		if len(allrslt) > 0:
			translations = [self.translate_object(allrslt[i][0],allrslt[i][1],allrslt[i][2],allrslt[i][3]) for i in range(len(allrslt))]
			rslt = translate_list(translations)
			self.getLog().setFinalAnswer(rslt)
		else:
			rslt = "I don't know."
			self.getLog().setFinalAnswer(rslt)
		return self.getLog(final=True)
		
		
	def listObjects(self):
		sql = "SELECT id,`name`,`type`,definite FROM Object"
		self.getCursor().execute(sql)
		allrslt = self.getCursor().fetchall()
		rslt = [(allrslt[i][0],self.translate_object(allrslt[i][0],allrslt[i][1],allrslt[i][2],allrslt[i][3])) for i in range(len(allrslt))]
		self.getLog(final=True)
		return rslt
